package com.jihong.plus;

import com.jihong.plus.util.EncryptHandler;
import com.jihong.plus.util.MyConfig;
import com.mysql.cj.protocol.ColumnDefinition;
import com.mysql.cj.result.Field;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

@Intercepts({
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})

})
public class ResultInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        MetaObject metaObject = SystemMetaObject.forObject(invocation);
        ColumnDefinition defaultColumnDefinition = (ColumnDefinition) metaObject.getValue("args[0].results.columnDefinition");
        if (defaultColumnDefinition == null){
            return invocation.proceed();
        }
        Field[] fields = defaultColumnDefinition.getFields();
        if (fields == null || fields.length == 0){
            return invocation.proceed();
        }
        List<MyConfig.EncryptData> needEnFieldList = MyConfig.getNeedEnField();
        List<String> encryptFieldList = new ArrayList<>(needEnFieldList.size());
        for (Field field : fields) {
            String name = field.getName();
            for (MyConfig.EncryptData encryptData : needEnFieldList) {
                String needEncryptField = encryptData.getField();
                if (needEncryptField.equals(name)){
                    MetaObject fieldMetaObject = SystemMetaObject.forObject(field);
                    fieldMetaObject.setValue("columnName.string",name + "_xxx");
                    continue;
                }
                String encryptColumn = EncryptHandler.encryptColumn(needEncryptField);
                if (encryptColumn.equals(name)){
                    MetaObject fieldMetaObject = SystemMetaObject.forObject(field);
                    String oldField = EncryptHandler.decryptColumn(encryptColumn);
                    fieldMetaObject.setValue("columnName.string",EncryptHandler.decryptColumn(encryptColumn));
                    encryptFieldList.add(oldField);
                }
            }
        }
        List<Object> proceed = (List<Object>) invocation.proceed();
        if (encryptFieldList.isEmpty()){
            return proceed;
        }
        for (Object o : proceed) {
            MetaObject entityMetaObject = SystemMetaObject.forObject(o);
            for (String encryptField : encryptFieldList) {
                String property = entityMetaObject.findProperty(encryptField, true);
                if (property == null){
                    continue;
                }
                Object value = entityMetaObject.getValue(property);
                if (value != null){
                    entityMetaObject.setValue(property,EncryptHandler.decryptValue(String.valueOf(value)));
                }
            }
        }
        return proceed;
    }
}